/*
 * Menu: Actionscript > Convention Generator
 * Key: M3+1
 * DOM: http://download.eclipse.org/technology/dash/update/org.eclipse.eclipsemonkey.lang.javascript
 * Author: Yi Tan
 * MoreInfo: http://code.google.com/p/yis-eclipse-monkey-scripts-for-flash-builder/
 */

/**
 * [What's this]
 * This script automatically converts input to class properties.
 * 
 * For example:
 * 
 * Your enter: 
 * -propertyName:n=
 * 
 * It will be converted to:
 * private var propertyName:Number= 0;
 * 
 *
 * [Shortcut Key]
 *
 * Alt + 1
 *
 * [How to use]
 *
 * Pleae check the how to slides
 *
 * http://www.slideshare.net/halfmile/convention-generator-yis-eclipse-monkey-scripts-for-flash-builder
 * 
 * [Change log]
 *	  
 *	 2009/11/11   Fix bug: fail to parse property name when there is input for the data type
 *	 2009/11/6    Add condition checking for nil selection
 *   2009/10/31   First version
 *
 */

var ACCESS_TYPE_PUBLIC = "+";
var ACCESS_TYPE_PRIVATE = "-";
var ACCESS_TYPE_PROTECTED = "*";

var ALL_ACCESS_TYPES = "+-*";

var ACCESS_TYPES = {"+":"public", "-":"private", "*":"protected"};

var MEMBER_TYPE_METHOD = "method";
var MEMBER_TYPE_PROPERTY = "property";

var DATA_TYPE_DEFAULT_VALUES = {
	"Object":"{}",
	"String":'""',
	"Boolean":"false",
	"Array":"[]",
	"Number":"0",
	"int":"0",
	"uint":"0",
	"Vector":"new Vector.<>()",
	"XML":'""'
};

var DATA_TYPE_ABBRES = {
	"o":"Object",
	"s":"String",
	"b":"Boolean",
	"a":"Array",
	"n":"Number",
	"i":"int",
	"u":"uint",
	"v":"Vector",
	"x":"XML"
}


function main()
{
  var editor = editors.activeEditor
  var source = editor.source


  if (!editor.selectionRange) return;

  var range  = editor.selectionRange;

  var offset = range.startingOffset;
	var text = (offset == range.endingOffset)?
		editor.source.split(editor.lineDelimiter)[editor.getLineAtOffset(editor.currentOffset)].replace(/^\s+|\s+$/g, ''):
		source.substring (offset, range.endingOffset);

	if (range.startingOffset == range.endingOffset) // when there is no selection 
		offset -= text.length;

	if (text.length < 1)
	{
		alert("Please select your input.");
		return;
	}
  
	// auto TODO
	if (text == "td")
	{
		editor.applyEdit(offset, range.endingOffset - offset, "// TODO: Need Implementation ");
		return;
	}


	// detect property type
	var memberType = (text.search(/\(\)/) != -1) ? MEMBER_TYPE_METHOD : MEMBER_TYPE_PROPERTY;

	// add default access type
    if (ALL_ACCESS_TYPES.indexOf(text[0]) == -1) text = "+"+text;

    switch(memberType){
		case MEMBER_TYPE_METHOD:
			// result = generateMethod(text);
			
			text = text.replace(text[0], ACCESS_TYPES[text[0]] + " function ");

			var dataType = text.match(/\:\w+/)
				
			if(! dataType) 
			{
				text += ":void";
			}
			else
			{
				dataType = dataType[0].replace(":","");	
				
				// parse data type abbrevations
				if (dataType.length == 1)
				{
					var fullDataType = DATA_TYPE_ABBRES[dataType.toLowerCase()] || dataType;
					// alert("fullDataType :"+fullDataType );

					text = text.replace(":"+dataType, ":"+fullDataType);
				}
			}

			text += "\n{\n\n}" ;
		    
			break;
		case MEMBER_TYPE_PROPERTY:

			// get propertyName and data type
			if(text.indexOf(":") != -1)
			{

				var propertyName = text.match(/\w+\:/)[0].replace(/\:/,"");
				var dataType = text.match(/\:\w+/)[0].replace(":","");
			}
			else
			{	// no input for data type
				var propertyName = text.match(/\w+/)[0];
				var dataType = "* ";
			}

			// append declaration
			var declaration = " var ";

			if (text.indexOf("$$") != -1) // $$ -> static const
			{
				declaration = " static const ";

				text = text.replace(propertyName, propertyName.toUpperCase());

				text = text.replace("$$", "");
			}
			else if(text.indexOf("$") != -1) // $ -> static
			{
				declaration = " static var ";
				text = text.replace("$", "");
			}
			text = text.replace(text[0], ACCESS_TYPES[text[0]] + declaration);

			// parse data type abbrevations
			if (dataType.length == 1)
			{
				var fullDataType = DATA_TYPE_ABBRES[dataType.toLowerCase()] || dataType;
				// alert("fullDataType :"+fullDataType );

				text = text.replace(":"+dataType, ":"+fullDataType);

				dataType = fullDataType;
			}

			// append default value if required
			if (text.lastIndexOf("=") == text.length -1 )
			{
				var defaultValue = DATA_TYPE_DEFAULT_VALUES[dataType] || "null" ;
				text += " "+defaultValue;
			}

			text += ";";

			// auto getter and setter
			if(propertyName[0] == "_")
			{
				// alert("// auto getter and setter");

				var accessorName = propertyName.substr(1);
				text += "\n\n public function get "+accessorName+"():"+dataType+"\n{\nreturn null;\n}";
				text += "\n\n public function set "+accessorName+"(value:"+dataType+"):void\n{\n\n}";
			}

			break;
	}

  // var result = "public static const " + text + ":String =  '" + text.toLowerCase() + "';";
 
  editor.applyEdit(offset, range.endingOffset - offset, text);

}
